/**
 * @file senior_part.cpp
 * @brief Brief description of senior_part.cpp
 * @author achdu0000@163.com
 * @version 1.0.0
 * @date 2024/07/20
 */

#include "senior_part.h"

// ==================================================
// =============== PRE-DECLARE ======================
// ==================================================

LV_IMG_DECLARE(img_60jiazi_and_24jieqi_480x480)
LV_IMG_DECLARE(img_icon_buzzer_30x30)

LV_FONT_DECLARE(lv_font_yahei_bold_16)

LV_FONT_DECLARE(lv_font_yahei_bold_12)

extern int lcd_mode;
extern int last_lcd_mode;
// ==================================================
// =============== DEFINATIONS ======================
// ==================================================

// ==================================================
// =============== STATIC VARIABLES =================
// ==================================================
/**
 * record the senior part of the lcd display
 * LCD_POS_LEFT: left part, only show screen
 * LCD_POS_CENTER: center part, show screen + extend1
 * LCD_POS_RIGHT: right part, show screen + extend1 + extend2
 */
enum LCD_POSITION {
    LCD_POS_LEFT = 0,
    LCD_POS_CENTER,
    LCD_POS_RIGHT
} lcd_position = LCD_POS_RIGHT;

enum CLOCK_MODE
{
    CM_NORMAL = 0,
    CM_SNOR,
    CM_TEST
};
CLOCK_MODE clock_mode = CM_NORMAL;

static lv_coord_t clock_width = -1;
static lv_coord_t clock_height = -1;

static lv_color_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(CANVAS_WIDTH, CANVAS_HEIGHT)];

static bool mode_switch_disabled = false;
static lv_timer_t *disable_timer;

// ==================================================
// =============== VARIABLES ========================
// ==================================================

lv_obj_t *canvas = nullptr;

lv_obj_t *buzzer_btn = nullptr;

lv_obj_t *clock_mode_label = nullptr;

// ==================================================
// =============== STATIC FUNCTION ==================
// ==================================================

/**
 * create basic clock ui
 * @param parent        the parent in lvgl widget
 * @return              true if success
 */
static bool create_basic_clock(lv_obj_t *parent);

/** create basic clock title label
 * @param parent        the parent in lvgl widget
 * @param x_ofs         the offset in direction x from the center of parent
 * @param y_ofs         the offset in direction y from the center of parent
 * @return              true if success
 */
static bool create_basic_clock_title_label_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs);

/** create extend 2 buzzer btn ui
 * @param parent        the parent in lvgl widget
 * @param x_ofs         the offset in direction x from the center of parent
 * @param y_ofs         the offset in direction y from the center of parent
 * @return              true if success
 */
static bool create_extend_2_buzzer_btn_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs);

/** create extend 2 clock model label ui
 * @param parent        the parent in lvgl widget
 * @param x_ofs         the offset in direction x from the center of parent
 * @param y_ofs         the offset in direction y from the center of parent
 * @return              true if success
 */
static bool create_extend_2_clock_mode_label_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs);

/**
 * init canvas used in extend 1 and extend 2 ui
 * @param parent        the parent in lvgl widget
 * @return              true if success
 */
static bool init_canvas(lv_obj_t *parent);

/**
 * create extend 1 clock ui
 * @param parent        the parent in lvgl widget
 * @return              true if success
 */
static bool create_extend_1_clock(lv_obj_t *parent);

/**
 * create extend 2 clock ui
 * @param parent        the parent in lvgl widget
 * @return              true if success
 */
static bool create_extend_2_clock(lv_obj_t *parent);

// ==================================================
// =============== IMPLEMENTATION ===================
// ==================================================

static bool create_basic_clock_title_label_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs)
{
    lv_obj_t *label = lv_label_create(parent);
    lv_label_set_text(label, "五时潮汐·人人上医");
    lv_obj_set_style_text_font(label, &lv_font_yahei_bold_16, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(label, lv_color_make(56, 87, 35), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_align(label, LV_ALIGN_CENTER, x_ofs, y_ofs);

    return true;
}

static bool create_extend_2_buzzer_btn_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs)
{
    buzzer_btn = lv_btn_create(parent);
    lv_obj_set_size(buzzer_btn, 30, 30);
    lv_obj_set_style_bg_img_src(buzzer_btn, &img_icon_buzzer_30x30, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(buzzer_btn, 0, LV_PART_MAIN | LV_STATE_ANY);
    lv_obj_set_style_radius(buzzer_btn, 0, LV_PART_MAIN | LV_STATE_ANY);
    lv_obj_set_style_shadow_width(buzzer_btn, 0, LV_PART_MAIN | LV_STATE_ANY);
    lv_obj_set_style_bg_opa(buzzer_btn, LV_OPA_TRANSP, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(buzzer_btn, SCREEN_FG_COLOR, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_add_flag(buzzer_btn, LV_OBJ_FLAG_CHECKABLE);
    // lv_obj_add_event_cb(buzzer_btn, btn_click_event_cb, LV_EVENT_CLICKED, nullptr);
    lv_obj_align_to(buzzer_btn, parent, LV_ALIGN_CENTER, x_ofs, y_ofs);
    return true;
}

static bool create_extend_2_clock_mode_label_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs)
{
    clock_mode_label = lv_label_create(parent);
    lv_obj_set_style_text_font(clock_mode_label, &lv_font_yahei_bold_12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(clock_mode_label, SCREEN_FG_COLOR, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(clock_mode_label, SCREEN_BG_COLOR, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(clock_mode_label, LV_OPA_COVER, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(clock_mode_label, (clock_mode == CM_NORMAL ? "正常模式" : (clock_mode == CM_SNOR ? "止鼾模式" : "测试模式")));
    lv_obj_align_to(clock_mode_label, parent, LV_ALIGN_CENTER, x_ofs, y_ofs);
    return true;
}

static bool create_basic_clock(lv_obj_t *parent)
{

    lv_coord_t width;
    lv_coord_t height;

    create_basic_sixty_jiazi_clock_ui(parent, clock_width, clock_height, &width, &height);

    create_basic_twenty_four_jieqi_clock_ui(parent, width, height, &width, &height);

    create_basic_hour_and_minute_clock_ui(parent, width, height, &width, &height);

    create_basic_clock_title_label_ui(parent, 0, -140);

    create_basic_birth_circle_ui(parent, 65);

    create_basic_icon_people_with_heart_ui(parent);

    create_basic_gps_icon_and_label_ui(parent, 0, 140);

    return true;
}

static bool init_canvas(lv_obj_t *parent)
{
    if (canvas == nullptr)
    {
        canvas = lv_canvas_create(parent);
        lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_TRUE_COLOR_ALPHA);
        lv_canvas_fill_bg(canvas, lv_palette_main(LV_PALETTE_AMBER), LV_OPA_TRANSP);
        lv_obj_center(canvas);
    }
    return true;
}

static bool create_extend_1_clock(lv_obj_t *parent)
{

    create_extend_1_local_ellipse_and_earth_moon_ui_with_canvas(parent, canvas, 0, 0, CANVAS_WIDTH, 140, 85, 68);

    create_extend_1_sun_track_and_sun_ui(parent, -16, -65);

    lv_obj_t *img_text = lv_img_create(parent);
    lv_img_set_src(img_text, &img_60jiazi_and_24jieqi_480x480);
    lv_obj_center(img_text);

    create_extend_1_sun_time_connect_people_ui(parent, 240);

    create_extend_1_local_time_connect_people_ui(parent, 213);

    return true;
}

static bool create_extend_2_clock(lv_obj_t *parent)
{

    create_extend_2_local_sunrise_and_sunset_ui(parent, -125, -5);

    create_extend_2_local_moonrise_and_moonset_ui(parent, -128, 20);

    create_extend_2_body_health_param_info_ui(parent, 110, -22);

    create_extend_2_year_ganzhi_label_ui(parent, -150, -35);
    create_extend_2_month_ganzhi_label_ui(parent, -130, 50);
    create_extend_2_day_ganzhi_label_ui(parent, -70, 67);
    create_extend_2_hour_ganzhi_and_open_meridian_label_ui(parent, 70, 67);

    create_extend_2_buzzer_btn_ui(parent, -100, 100);

    create_extend_2_guide_text_label_ui(parent, 100, 90);

    create_extend_2_body_psi_ui_with_canvas(parent, canvas, 10, 140 + 5, CANVAS_WIDTH - 10 * 2, CANVAS_HEIGHT - 140 - 5);

    create_extend_2_body_yin_yang_ui_with_canvas(parent, canvas, 0, 9, CANVAS_WIDTH, 140, 60);

    create_extend_2_body_yin_yang_label_ui(parent, 0, 0, 68);

    create_extend_2_clock_mode_label_ui(parent, 0, -50);

    return true;
}

static lv_obj_t *extend_1 = nullptr;
static lv_obj_t *extend_2 = nullptr;

void my_event_cb(lv_event_t *e)
{
    lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act());
    LV_LOG_INFO("Gesture: %s", dir == LV_DIR_LEFT ? "Left" : "Right");
    LV_LOG_INFO("LCD_POSITION: %d", lcd_position);
    if (dir == LV_DIR_LEFT)
    {
        if (lcd_position == LCD_POS_LEFT) {
            lcd_position = LCD_POS_CENTER;
            // TODO move to center
            lv_obj_clear_flag(extend_1, LV_OBJ_FLAG_HIDDEN);
            erase_canvas(canvas);
            create_extend_1_local_ellipse_and_earth_moon_ui_with_canvas(extend_1, canvas, 0, 0, CANVAS_WIDTH, 140, 85, 68);
        } else if (lcd_position == LCD_POS_CENTER) {
            lcd_position = LCD_POS_RIGHT;
            // TODO move to right
            lv_obj_clear_flag(extend_2, LV_OBJ_FLAG_HIDDEN);
            
            create_extend_2_body_psi_ui_with_canvas(extend_2, canvas, 10, 140 + 5, CANVAS_WIDTH - 10 * 2, CANVAS_HEIGHT - 140 - 5);

            create_extend_2_body_yin_yang_ui_with_canvas(extend_2, canvas, 0, 9, CANVAS_WIDTH, 140, 60);
        } else if (lcd_position == LCD_POS_RIGHT) {
            ;
        }
    }
    else if (dir == LV_DIR_RIGHT)
    {
        if (lcd_position == LCD_POS_RIGHT) {
            lcd_position = LCD_POS_CENTER;
            // TODO move to center
            lv_obj_add_flag(extend_2, LV_OBJ_FLAG_HIDDEN);
            erase_canvas(canvas);
            create_extend_1_local_ellipse_and_earth_moon_ui_with_canvas(extend_1, canvas, 0, 0, CANVAS_WIDTH, 140, 85, 68);
        } else if (lcd_position == LCD_POS_CENTER) {
            lcd_position = LCD_POS_LEFT;
            // TODO move to left
            lv_obj_add_flag(extend_1, LV_OBJ_FLAG_HIDDEN);
            erase_canvas(canvas);
        } else if (lcd_position == LCD_POS_LEFT) {
            ;
        } 
    }
}


bool set_vals()
{
    set_now_time_val(2024, 7, 31, 16, 35);
    set_now_year_ganzhi("甲辰");
    set_now_month_ganzhi("辛未");
    set_now_day_ganzhi("丙申");
    set_now_hour_ganzhi("丙申");

    set_jieqi_wuhou_val("大暑", 2);
    set_local_gps_val(117, 20, 11, 38, 59, 9);

    set_birth_time_val(2002, 10, 9, 8, 7, "壬午", "寒露", 1);
    set_birth_year_jiazi_val("壬午");

    set_birth_jieqi_wuhou_val("寒露", 1);

    set_local_sunrise_and_sunset_val(4, 56, 19, 37);
    set_local_moonrise_and_moonset_val(11, 49, 23, 21);

    set_body_temperature_val(365);
    set_body_blood_press_val(120, 80);
    set_body_blood_oxygen_val(98);
    set_body_heart_rate_val(76);
    set_body_walk_step_val(12345);
    set_body_state_str("疲 惫");

    set_body_yinyang_val(85, 72);

    return true;
}

static void create_extend_1_clock_timer_xcb(lv_timer_t *timer)
{
    lv_obj_t *parent = (lv_obj_t *)(timer->user_data);

    extend_1 = lv_obj_create(parent);
    lv_obj_remove_style_all(extend_1);
    lv_obj_set_size(extend_1, clock_width, clock_height);

    init_canvas(extend_1);

    create_extend_1_clock(extend_1);

    lv_obj_move_foreground(get_basic_hour_and_minute_clock_meter_obj());
    lv_obj_move_foreground(get_basic_icon_people_with_heart_obj());

    lv_timer_del(timer);
}

static void create_extend_2_clock_timer_xcb(lv_timer_t *timer)
{
    lv_obj_t *parent = (lv_obj_t *)(timer->user_data);

    extend_2 = lv_obj_create(parent);
    lv_obj_remove_style_all(extend_2);
    lv_obj_set_size(extend_2, clock_width, clock_height);

    create_extend_2_clock(extend_2);

    lv_obj_move_foreground(get_basic_hour_and_minute_clock_meter_obj());
    lv_obj_move_foreground(get_basic_icon_people_with_heart_obj());
    lv_obj_move_foreground(buzzer_btn);

    lv_obj_add_event_cb(parent, my_event_cb, LV_EVENT_GESTURE, nullptr);
    lv_obj_add_event_cb(extend_1, my_event_cb, LV_EVENT_GESTURE, nullptr);
    lv_obj_add_event_cb(extend_2, my_event_cb, LV_EVENT_GESTURE, nullptr);
    lv_timer_del(timer);
}

static void disable_timer_cb(lv_timer_t *timer)
{
    mode_switch_disabled = false;
}

static bool change_clock_mode()
{
    mode_switch_disabled = true;

    if (!disable_timer)
    {
        disable_timer = lv_timer_create(disable_timer_cb, 3000, nullptr);
        // lv_timer_set_repeat_count(disable_timer, 1);
    }
    else
    {
        lv_timer_del(disable_timer);
        disable_timer = lv_timer_create(disable_timer_cb, 3000, nullptr);
        // lv_timer_set_repeat_count(disable_timer, 1);
    }

    if (extend_2 == nullptr)
        return false;
    if (clock_mode == CM_NORMAL)
    {
        clock_mode = CM_SNOR;
        lv_label_set_text(clock_mode_label, "止鼾模式");
        last_lcd_mode = lcd_mode;
        lcd_mode = 3;
    }
    else if (clock_mode == CM_SNOR)
    {
        clock_mode = CM_TEST;
        lv_label_set_text(clock_mode_label, "测试模式");
        last_lcd_mode = lcd_mode;
        lcd_mode = 4;
    }
    else
    {
        clock_mode = CM_NORMAL;
        lv_label_set_text(clock_mode_label, "正常模式");
        last_lcd_mode = lcd_mode;
        lcd_mode = 2;

    }

    return true;
}

static void change_clock_mode_event_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED && !mode_switch_disabled)
    {
        lv_indev_t *indev = lv_indev_get_act();
        lv_point_t point;
        if (indev)
        {
            lv_indev_get_point(indev, &point);

            char buf[128];
            lv_snprintf(buf, sizeof(buf), "p_x = %d, p_y = %d", point.x, point.y);
            LV_LOG_INFO(buf);

            if ((point.x - clock_width / 2) * (point.x - clock_width / 2) + (point.y - clock_height / 2) * (point.y - clock_height / 2) < 65 * 65)
            {
                change_clock_mode();
            }
        }
    }
}

bool senior_part_on_create(lv_obj_t *parent)
{
    clock_width = lv_obj_get_width(parent);
    clock_height = lv_obj_get_height(parent);

    lv_obj_set_style_bg_color(parent, SCREEN_BG_COLOR, LV_PART_MAIN | LV_STATE_DEFAULT);

    set_vals();

    create_basic_clock(parent);

    lv_timer_create(create_extend_1_clock_timer_xcb, 1000, (void *)parent);
    // create_extend_1_clock(extend_1);

    lv_timer_create(create_extend_2_clock_timer_xcb, 1000 + 1000, (void *)parent);

    lcd_position = LCD_POS_RIGHT;
    lv_obj_add_event_cb(get_basic_hour_and_minute_clock_meter_obj(), change_clock_mode_event_cb, LV_EVENT_ALL, nullptr);

    return true;
}

void erase_canvas(lv_obj_t *canvas) {
    for (int i = 0; i < CANVAS_WIDTH; i++) {
        for (int j = 0; j < CANVAS_HEIGHT; j++) {
            lv_canvas_set_px_color(canvas, i, j, SCREEN_BG_COLOR);
            lv_canvas_set_px_opa(canvas, i, j, 0);
        }
    }
}